Changes to support satellite stats appear as TYPE_MOBILE
With satellite transport supported at device and satellite
network to appear under type mobile, considers cellular or
satellite, or combination of both interfaces under mobile interfaces.
Note: getUidStatsForTransport(TRANSPORT_SATELLITE) is not supported,
considering the same interface name could be used by cellular as well,
supporting this might lead to double counting problem.
Bug: 329003473
Test: atest FrameworksNetTests
Change-Id: I85465cedcc5550fa0555dc36b3be364ac90aade1
diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java
index 7fa0661..18c839f 100644
--- a/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -752,8 +752,8 @@
/**
* Query realtime mobile network usage statistics.
*
- * Return a snapshot of current UID network statistics, as it applies
- * to the mobile radios of the device. The snapshot will include any
+ * Return a snapshot of current UID network statistics for both cellular and satellite (which
+ * also uses same mobile radio as cellular) when called. The snapshot will include any
* tethering traffic, video calling data usage and count of
* network operations set by {@link TrafficStats#incrementOperationCount}
* made over a mobile radio.
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 64b17eb..1fb87a2 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -1778,6 +1778,8 @@
if (transport == TRANSPORT_WIFI) {
ifaceSet = mAllWifiIfacesSinceBoot;
} else if (transport == TRANSPORT_CELLULAR) {
+ // Since satellite networks appear under type mobile, this includes both cellular
+ // and satellite active interfaces
ifaceSet = mAllMobileIfacesSinceBoot;
} else {
throw new IllegalArgumentException("Invalid transport " + transport);
@@ -2187,7 +2189,9 @@
for (NetworkStateSnapshot snapshot : snapshots) {
final int displayTransport =
getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
- final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
+ // Consider satellite transport to support satellite stats appear as type_mobile
+ final boolean isMobile = NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport
+ || NetworkCapabilities.TRANSPORT_SATELLITE == displayTransport;
final boolean isWifi = (NetworkCapabilities.TRANSPORT_WIFI == displayTransport);
final boolean isDefault = CollectionUtils.contains(
mDefaultNetworks, snapshot.getNetwork());
@@ -2320,12 +2324,14 @@
}
/**
- * For networks with {@code TRANSPORT_CELLULAR}, get ratType that was obtained through
- * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
- * transport types do not actually fill this value.
+ * For networks with {@code TRANSPORT_CELLULAR} Or {@code TRANSPORT_SATELLITE}, get ratType
+ * that was obtained through {@link PhoneStateListener}. Otherwise, return 0 given that other
+ * networks with different transport types do not actually fill this value.
*/
private int getRatTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
- if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && !state.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)) {
return 0;
}
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java b/staticlibs/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java
index 54ce01e..fa07885 100644
--- a/staticlibs/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java
+++ b/staticlibs/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java
@@ -39,6 +39,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_SATELLITE;
import static android.net.NetworkCapabilities.TRANSPORT_USB;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -75,8 +76,8 @@
TRANSPORT_BLUETOOTH,
TRANSPORT_WIFI,
TRANSPORT_ETHERNET,
- TRANSPORT_USB
-
+ TRANSPORT_USB,
+ TRANSPORT_SATELLITE
// Notably, TRANSPORT_TEST is not in this list as any network that has TRANSPORT_TEST and
// one of the above transports should be counted as that transport, to keep tests as
// realistic as possible.
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 3d7ad66..81d1550 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -910,7 +910,16 @@
}
@Test
- public void testMobileStatsByRatType() throws Exception {
+ public void testMobileStatsByRatTypeForSatellite() throws Exception {
+ doTestMobileStatsByRatType(new NetworkStateSnapshot[]{buildSatelliteMobileState(IMSI_1)});
+ }
+
+ @Test
+ public void testMobileStatsByRatTypeForCellular() throws Exception {
+ doTestMobileStatsByRatType(new NetworkStateSnapshot[]{buildMobileState(IMSI_1)});
+ }
+
+ private void doTestMobileStatsByRatType(NetworkStateSnapshot[] states) throws Exception {
final NetworkTemplate template3g = new NetworkTemplate.Builder(MATCH_MOBILE)
.setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
.setMeteredness(METERED_YES).build();
@@ -920,8 +929,6 @@
final NetworkTemplate template5g = new NetworkTemplate.Builder(MATCH_MOBILE)
.setRatType(TelephonyManager.NETWORK_TYPE_NR)
.setMeteredness(METERED_YES).build();
- final NetworkStateSnapshot[] states =
- new NetworkStateSnapshot[]{buildMobileState(IMSI_1)};
// 3G network comes online.
mockNetworkStatsSummary(buildEmptyStats());
@@ -935,7 +942,7 @@
incrementCurrentTime(MINUTE_IN_MILLIS);
mockNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
- METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 12L, 18L, 14L, 1L, 0L)));
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 12L, 18L, 14L, 1L, 0L)));
forcePollAndWaitForIdle();
// Verify 3g templates gets stats.
@@ -950,7 +957,7 @@
mockNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
// Append more traffic on existing 3g stats entry.
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
- METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 16L, 22L, 17L, 2L, 0L))
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 16L, 22L, 17L, 2L, 0L))
// Add entry that is new on 4g.
.addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE,
METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 33L, 27L, 8L, 10L, 1L)));
@@ -1352,6 +1359,57 @@
}
@Test
+ public void testGetUidStatsForTransportWithCellularAndSatellite() throws Exception {
+ // Setup satellite mobile network and Cellular mobile network
+ mockDefaultSettings();
+ mockNetworkStatsUidDetail(buildEmptyStats());
+
+ final NetworkStateSnapshot mobileState = buildStateOfTransport(
+ NetworkCapabilities.TRANSPORT_CELLULAR, TYPE_MOBILE,
+ TEST_IFACE2, IMSI_1, null /* wifiNetworkKey */,
+ false /* isTemporarilyNotMetered */, false /* isRoaming */);
+
+ final NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{mobileState,
+ buildSatelliteMobileState(IMSI_1)};
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
+ setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE);
+
+ // mock traffic on satellite network
+ final NetworkStats.Entry entrySatellite = new NetworkStats.Entry(
+ TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 80L, 5L, 70L, 15L, 1L);
+
+ // mock traffic on cellular network
+ final NetworkStats.Entry entryCellular = new NetworkStats.Entry(
+ TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 100L, 15L, 150L, 15L, 1L);
+
+ final TetherStatsParcel[] emptyTetherStats = {};
+ // The interfaces that expect to be used to query the stats.
+ final String[] mobileIfaces = {TEST_IFACE, TEST_IFACE2};
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ mockDefaultSettings();
+ mockNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
+ .insertEntry(entrySatellite).insertEntry(entryCellular), emptyTetherStats,
+ mobileIfaces);
+ // with getUidStatsForTransport(TRANSPORT_CELLULAR) return stats of both cellular
+ // and satellite
+ final NetworkStats mobileStats = mService.getUidStatsForTransport(
+ NetworkCapabilities.TRANSPORT_CELLULAR);
+
+ // The iface field of the returned stats should be null because getUidStatsForTransport
+ // clears the interface field before it returns the result.
+ assertValues(mobileStats, null /* iface */, UID_RED, SET_DEFAULT, TAG_NONE,
+ METERED_NO, ROAMING_NO, METERED_NO, 180L, 20L, 220L, 30L, 2L);
+
+ // getUidStatsForTransport(TRANSPORT_SATELLITE) is not supported
+ assertThrows(IllegalArgumentException.class,
+ () -> mService.getUidStatsForTransport(NetworkCapabilities.TRANSPORT_SATELLITE));
+
+ }
+
+ @Test
public void testForegroundBackground() throws Exception {
// pretend that network comes online
mockDefaultSettings();
@@ -2509,6 +2567,12 @@
false /* isTemporarilyNotMetered */, false /* isRoaming */);
}
+ private static NetworkStateSnapshot buildSatelliteMobileState(String subscriberId) {
+ return buildStateOfTransport(NetworkCapabilities.TRANSPORT_SATELLITE, TYPE_MOBILE,
+ TEST_IFACE, subscriberId, null /* wifiNetworkKey */,
+ false /* isTemporarilyNotMetered */, false /* isRoaming */);
+ }
+
private static NetworkStateSnapshot buildTestState(@NonNull String iface,
@Nullable String wifiNetworkKey) {
return buildStateOfTransport(NetworkCapabilities.TRANSPORT_TEST, TYPE_TEST,