[AF01] Move NetworkStatsCollection comparison code to NetworkStatsCollection
This is a no-op refactoring to move the ultility method to a
common place to be referenced outside NetworkStatsService
in later patches.
Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.net.NetworkStatsServiceTest
Bug: 313841499
Change-Id: Ib0ef40d87486bf3d8d5b3f97c77291a00c0378ac
diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java
index 20c5f30..b6f6dbb 100644
--- a/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/framework-t/src/android/net/NetworkStatsCollection.java
@@ -26,6 +26,7 @@
import static android.net.NetworkStats.ROAMING_YES;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkTemplate.MATCH_BLUETOOTH;
@@ -50,6 +51,7 @@
import android.telephony.SubscriptionPlan;
import android.text.format.DateUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.IndentingPrintWriter;
import android.util.Log;
@@ -924,6 +926,100 @@
}
}
+
+ private static String str(NetworkStatsCollection.Key key) {
+ StringBuilder sb = new StringBuilder()
+ .append(key.ident.toString())
+ .append(" uid=").append(key.uid);
+ if (key.set != SET_FOREGROUND) {
+ sb.append(" set=").append(key.set);
+ }
+ if (key.tag != 0) {
+ sb.append(" tag=").append(key.tag);
+ }
+ return sb.toString();
+ }
+
+ // The importer will modify some keys when importing them.
+ // In order to keep the comparison code simple, add such special cases here and simply
+ // ignore them. This should not impact fidelity much because the start/end checks and the total
+ // bytes check still need to pass.
+ private static boolean couldKeyChangeOnImport(NetworkStatsCollection.Key key) {
+ if (key.ident.isEmpty()) return false;
+ final NetworkIdentity firstIdent = key.ident.iterator().next();
+
+ // Non-mobile network with non-empty RAT type.
+ // This combination is invalid and the NetworkIdentity.Builder will throw if it is passed
+ // in, but it looks like it was previously possible to persist it to disk. The importer sets
+ // the RAT type to NETWORK_TYPE_ALL.
+ if (firstIdent.getType() != ConnectivityManager.TYPE_MOBILE
+ && firstIdent.getRatType() != NetworkTemplate.NETWORK_TYPE_ALL) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compare two {@link NetworkStatsCollection} instances and returning a human-readable
+ * string description of difference for debugging purpose.
+ *
+ * @hide
+ */
+ @Nullable
+ public static String compareStats(
+ NetworkStatsCollection migrated, NetworkStatsCollection legacy) {
+ final Map<NetworkStatsCollection.Key, NetworkStatsHistory> migEntries =
+ migrated.getEntries();
+ final Map<NetworkStatsCollection.Key, NetworkStatsHistory> legEntries = legacy.getEntries();
+
+ final ArraySet<NetworkStatsCollection.Key> unmatchedLegKeys =
+ new ArraySet<>(legEntries.keySet());
+
+ for (NetworkStatsCollection.Key legKey : legEntries.keySet()) {
+ final NetworkStatsHistory legHistory = legEntries.get(legKey);
+ final NetworkStatsHistory migHistory = migEntries.get(legKey);
+
+ if (migHistory == null && couldKeyChangeOnImport(legKey)) {
+ unmatchedLegKeys.remove(legKey);
+ continue;
+ }
+
+ if (migHistory == null) {
+ return "Missing migrated history for legacy key " + str(legKey)
+ + ", legacy history was " + legHistory;
+ }
+ if (!migHistory.isSameAs(legHistory)) {
+ return "Difference in history for key " + legKey + "; legacy history " + legHistory
+ + ", migrated history " + migHistory;
+ }
+ unmatchedLegKeys.remove(legKey);
+ }
+
+ if (!unmatchedLegKeys.isEmpty()) {
+ final NetworkStatsHistory first = legEntries.get(unmatchedLegKeys.valueAt(0));
+ return "Found unmatched legacy keys: count=" + unmatchedLegKeys.size()
+ + ", first unmatched collection " + first;
+ }
+
+ if (migrated.getStartMillis() != legacy.getStartMillis()
+ || migrated.getEndMillis() != legacy.getEndMillis()) {
+ return "Start / end of the collections "
+ + migrated.getStartMillis() + "/" + legacy.getStartMillis() + " and "
+ + migrated.getEndMillis() + "/" + legacy.getEndMillis()
+ + " don't match";
+ }
+
+ if (migrated.getTotalBytes() != legacy.getTotalBytes()) {
+ return "Total bytes " + migrated.getTotalBytes() + " and " + legacy.getTotalBytes()
+ + " don't match for collections with start/end "
+ + migrated.getStartMillis()
+ + "/" + legacy.getStartMillis();
+ }
+
+ return null;
+ }
+
/**
* the identifier that associate with the {@link NetworkStatsHistory} object to identify
* a certain record in the {@link NetworkStatsCollection} object.
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 804e709..2c9f30c 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -44,6 +44,7 @@
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static android.net.NetworkStatsCollection.compareStats;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.MATCH_MOBILE;
import static android.net.NetworkTemplate.MATCH_TEST;
@@ -95,7 +96,6 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
-import android.net.ConnectivityManager;
import android.net.DataUsageRequest;
import android.net.INetd;
import android.net.INetworkStatsService;
@@ -1272,93 +1272,6 @@
return true;
}
- private static String str(NetworkStatsCollection.Key key) {
- StringBuilder sb = new StringBuilder()
- .append(key.ident.toString())
- .append(" uid=").append(key.uid);
- if (key.set != SET_FOREGROUND) {
- sb.append(" set=").append(key.set);
- }
- if (key.tag != 0) {
- sb.append(" tag=").append(key.tag);
- }
- return sb.toString();
- }
-
- // The importer will modify some keys when importing them.
- // In order to keep the comparison code simple, add such special cases here and simply
- // ignore them. This should not impact fidelity much because the start/end checks and the total
- // bytes check still need to pass.
- private static boolean couldKeyChangeOnImport(NetworkStatsCollection.Key key) {
- if (key.ident.isEmpty()) return false;
- final NetworkIdentity firstIdent = key.ident.iterator().next();
-
- // Non-mobile network with non-empty RAT type.
- // This combination is invalid and the NetworkIdentity.Builder will throw if it is passed
- // in, but it looks like it was previously possible to persist it to disk. The importer sets
- // the RAT type to NETWORK_TYPE_ALL.
- if (firstIdent.getType() != ConnectivityManager.TYPE_MOBILE
- && firstIdent.getRatType() != NetworkTemplate.NETWORK_TYPE_ALL) {
- return true;
- }
-
- return false;
- }
-
- @Nullable
- private static String compareStats(
- NetworkStatsCollection migrated, NetworkStatsCollection legacy) {
- final Map<NetworkStatsCollection.Key, NetworkStatsHistory> migEntries =
- migrated.getEntries();
- final Map<NetworkStatsCollection.Key, NetworkStatsHistory> legEntries = legacy.getEntries();
-
- final ArraySet<NetworkStatsCollection.Key> unmatchedLegKeys =
- new ArraySet<>(legEntries.keySet());
-
- for (NetworkStatsCollection.Key legKey : legEntries.keySet()) {
- final NetworkStatsHistory legHistory = legEntries.get(legKey);
- final NetworkStatsHistory migHistory = migEntries.get(legKey);
-
- if (migHistory == null && couldKeyChangeOnImport(legKey)) {
- unmatchedLegKeys.remove(legKey);
- continue;
- }
-
- if (migHistory == null) {
- return "Missing migrated history for legacy key " + str(legKey)
- + ", legacy history was " + legHistory;
- }
- if (!migHistory.isSameAs(legHistory)) {
- return "Difference in history for key " + legKey + "; legacy history " + legHistory
- + ", migrated history " + migHistory;
- }
- unmatchedLegKeys.remove(legKey);
- }
-
- if (!unmatchedLegKeys.isEmpty()) {
- final NetworkStatsHistory first = legEntries.get(unmatchedLegKeys.valueAt(0));
- return "Found unmatched legacy keys: count=" + unmatchedLegKeys.size()
- + ", first unmatched collection " + first;
- }
-
- if (migrated.getStartMillis() != legacy.getStartMillis()
- || migrated.getEndMillis() != legacy.getEndMillis()) {
- return "Start / end of the collections "
- + migrated.getStartMillis() + "/" + legacy.getStartMillis() + " and "
- + migrated.getEndMillis() + "/" + legacy.getEndMillis()
- + " don't match";
- }
-
- if (migrated.getTotalBytes() != legacy.getTotalBytes()) {
- return "Total bytes " + migrated.getTotalBytes() + " and " + legacy.getTotalBytes()
- + " don't match for collections with start/end "
- + migrated.getStartMillis()
- + "/" + legacy.getStartMillis();
- }
-
- return null;
- }
-
@GuardedBy("mStatsLock")
@NonNull
private NetworkStatsCollection readPlatformCollectionForRecorder(