diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index d0e0f70cf4..0ae227a9a4 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -1475,9 +1475,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // We've been using pure XT stats long enough that we no longer need to // splice DEV and XT together. final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL, - accessLevel, callingUid, start, end); + accessLevel, callingUid, Long.MIN_VALUE, Long.MAX_VALUE); - final long now = System.currentTimeMillis(); + final long now = mClock.millis(); final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); final NetworkStats stats = new NetworkStats(end - start, 1); diff --git a/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java index ec515376af..d1bf40ed56 100644 --- a/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java +++ b/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java @@ -27,6 +27,7 @@ import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_Q import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH; import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN; +import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; @@ -184,7 +185,7 @@ public class MultipathPolicyTrackerTest { (int) setting); } - private void testGetMultipathPreference( + private void prepareGetMultipathPreferenceTest( long usedBytesToday, long subscriptionQuota, long policyWarning, long policyLimit, long defaultGlobalSetting, long defaultResSetting, boolean roaming) { @@ -286,7 +287,7 @@ public class MultipathPolicyTrackerTest { @Test public void testGetMultipathPreference_SubscriptionQuota() { - testGetMultipathPreference( + prepareGetMultipathPreferenceTest( DataUnit.MEGABYTES.toBytes(2) /* usedBytesToday */, DataUnit.MEGABYTES.toBytes(14) /* subscriptionQuota */, DataUnit.MEGABYTES.toBytes(100) /* policyWarning */, @@ -301,7 +302,7 @@ public class MultipathPolicyTrackerTest { @Test public void testGetMultipathPreference_UserWarningQuota() { - testGetMultipathPreference( + prepareGetMultipathPreferenceTest( DataUnit.MEGABYTES.toBytes(7) /* usedBytesToday */, OPPORTUNISTIC_QUOTA_UNKNOWN, // Remaining days are 29 days from Apr. 2nd to May 1st. @@ -320,7 +321,7 @@ public class MultipathPolicyTrackerTest { @Test public void testGetMultipathPreference_SnoozedWarningQuota() { - testGetMultipathPreference( + prepareGetMultipathPreferenceTest( DataUnit.MEGABYTES.toBytes(7) /* usedBytesToday */, OPPORTUNISTIC_QUOTA_UNKNOWN, POLICY_SNOOZED /* policyWarning */, @@ -339,7 +340,7 @@ public class MultipathPolicyTrackerTest { @Test public void testGetMultipathPreference_SnoozedBothQuota() { - testGetMultipathPreference( + prepareGetMultipathPreferenceTest( DataUnit.MEGABYTES.toBytes(7) /* usedBytesToday */, OPPORTUNISTIC_QUOTA_UNKNOWN, // 29 days from Apr. 2nd to May 1st @@ -356,7 +357,7 @@ public class MultipathPolicyTrackerTest { @Test public void testGetMultipathPreference_SettingChanged() { - testGetMultipathPreference( + prepareGetMultipathPreferenceTest( DataUnit.MEGABYTES.toBytes(2) /* usedBytesToday */, OPPORTUNISTIC_QUOTA_UNKNOWN, WARNING_DISABLED, @@ -381,7 +382,7 @@ public class MultipathPolicyTrackerTest { @Test public void testGetMultipathPreference_ResourceChanged() { - testGetMultipathPreference( + prepareGetMultipathPreferenceTest( DataUnit.MEGABYTES.toBytes(2) /* usedBytesToday */, OPPORTUNISTIC_QUOTA_UNKNOWN, WARNING_DISABLED, @@ -404,4 +405,45 @@ public class MultipathPolicyTrackerTest { verify(mStatsManager, times(1)).registerUsageCallback( any(), eq(DataUnit.MEGABYTES.toBytes(14)), any(), any()); } + + @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) + @Test + public void testOnThresholdReached() { + prepareGetMultipathPreferenceTest( + DataUnit.MEGABYTES.toBytes(2) /* usedBytesToday */, + DataUnit.MEGABYTES.toBytes(14) /* subscriptionQuota */, + DataUnit.MEGABYTES.toBytes(100) /* policyWarning */, + LIMIT_DISABLED, + DataUnit.MEGABYTES.toBytes(12) /* defaultGlobalSetting */, + 2_500_000 /* defaultResSetting */, + false /* roaming */); + + final ArgumentCaptor usageCallbackCaptor = + ArgumentCaptor.forClass(NetworkStatsManager.UsageCallback.class); + final ArgumentCaptor networkTemplateCaptor = + ArgumentCaptor.forClass(NetworkTemplate.class); + // Verify the callback is registered with quota - used = 14 - 2 = 12MB. + verify(mStatsManager, times(1)).registerUsageCallback( + networkTemplateCaptor.capture(), eq(DataUnit.MEGABYTES.toBytes(12)), any(), + usageCallbackCaptor.capture()); + + // Capture arguments for later use. + final NetworkStatsManager.UsageCallback usageCallback = usageCallbackCaptor.getValue(); + final NetworkTemplate template = networkTemplateCaptor.getValue(); + assertNotNull(usageCallback); + assertNotNull(template); + + // Decrease quota from 14 to 11, and trigger the event. + // TODO: Mock daily and monthly used bytes instead of changing subscription to simulate + // remaining quota changed. + when(mNPMI.getSubscriptionOpportunisticQuota(TEST_NETWORK, QUOTA_TYPE_MULTIPATH)) + .thenReturn(DataUnit.MEGABYTES.toBytes(11)); + usageCallback.onThresholdReached(template); + + // Callback must have been re-registered with new remaining quota = 11 - 2 = 9MB. + verify(mStatsManager, times(1)) + .unregisterUsageCallback(eq(usageCallback)); + verify(mStatsManager, times(1)).registerUsageCallback( + eq(template), eq(DataUnit.MEGABYTES.toBytes(9)), any(), eq(usageCallback)); + } } diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java index 49f34703b1..3708d2e97e 100644 --- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java @@ -144,7 +144,10 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.time.Clock; +import java.time.ZoneId; import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; @@ -1104,6 +1107,40 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { DEFAULT_NETWORK_YES, 1024L, 8L, 512L, 4L, 0); } + @Test + public void testGetLatestSummary() throws Exception { + // Pretend that network comes online. + expectDefaultSettings(); + NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{buildWifiState()}; + expectNetworkStatsSummary(buildEmptyStats()); + expectNetworkStatsUidDetail(buildEmptyStats()); + + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), + new UnderlyingNetworkInfo[0]); + + // Increase arbitrary time which does not align to the bucket edge, create some traffic. + incrementCurrentTime(1751000L); + NetworkStats.Entry entry = new NetworkStats.Entry( + TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 50L, 5L, 51L, 1L, 3L); + expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1).insertEntry(entry)); + expectNetworkStatsUidDetail(buildEmptyStats()); + forcePollAndWaitForIdle(); + + // Verify the mocked stats is returned by querying with the range of the latest bucket. + final ZonedDateTime end = + ZonedDateTime.ofInstant(mClock.instant(), ZoneId.systemDefault()); + final ZonedDateTime start = end.truncatedTo(ChronoUnit.HOURS); + NetworkStats stats = mSession.getSummaryForNetwork(buildTemplateWifi(TEST_WIFI_NETWORK_KEY), + start.toInstant().toEpochMilli(), end.toInstant().toEpochMilli()); + assertEquals(1, stats.size()); + assertValues(stats, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 50L, 5L, 51L, 1L, 3L); + + // For getHistoryIntervalForNetwork, only includes buckets that atomically occur in + // the inclusive time range, instead of including the latest bucket. This behavior is + // already documented publicly, refer to {@link NetworkStatsManager#queryDetails}. + } + @Test public void testUidStatsForTransport() throws Exception { // pretend that network comes online