1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app.usage; 18 19 import static junit.framework.Assert.assertEquals; 20 import static junit.framework.Assert.assertFalse; 21 import static junit.framework.Assert.assertTrue; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyInt; 25 import static org.mockito.ArgumentMatchers.anyLong; 26 import static org.mockito.ArgumentMatchers.anyString; 27 import static org.mockito.ArgumentMatchers.argThat; 28 import static org.mockito.ArgumentMatchers.eq; 29 import static org.mockito.Mockito.times; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.when; 32 33 import android.net.ConnectivityManager; 34 import android.net.INetworkStatsService; 35 import android.net.INetworkStatsSession; 36 import android.net.NetworkStats.Entry; 37 import android.net.NetworkStatsHistory; 38 import android.net.NetworkTemplate; 39 import android.os.RemoteException; 40 41 import androidx.test.InstrumentationRegistry; 42 import androidx.test.filters.SmallTest; 43 import androidx.test.runner.AndroidJUnit4; 44 45 import org.junit.Before; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 import org.mockito.Mock; 49 import org.mockito.MockitoAnnotations; 50 import org.mockito.invocation.InvocationOnMock; 51 52 @RunWith(AndroidJUnit4.class) 53 @SmallTest 54 public class NetworkStatsManagerTest { 55 56 private @Mock INetworkStatsService mService; 57 private @Mock INetworkStatsSession mStatsSession; 58 59 private NetworkStatsManager mManager; 60 61 // TODO: change to NetworkTemplate.MATCH_MOBILE once internal constant rename is merged to aosp. 62 private static final int MATCH_MOBILE_ALL = 1; 63 64 @Before 65 public void setUp() { 66 MockitoAnnotations.initMocks(this); 67 mManager = new NetworkStatsManager(InstrumentationRegistry.getContext(), mService); 68 } 69 70 @Test 71 public void testQueryDetails() throws RemoteException { 72 final String subscriberId = "subid"; 73 final long startTime = 1; 74 final long endTime = 100; 75 final int uid1 = 10001; 76 final int uid2 = 10002; 77 final int uid3 = 10003; 78 79 Entry uid1Entry1 = new Entry("if1", uid1, 80 android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE, 81 100, 10, 200, 20, 0); 82 83 Entry uid1Entry2 = new Entry( 84 "if2", uid1, 85 android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE, 86 100, 10, 200, 20, 0); 87 88 Entry uid2Entry1 = new Entry("if1", uid2, 89 android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE, 90 150, 10, 250, 20, 0); 91 92 Entry uid2Entry2 = new Entry( 93 "if2", uid2, 94 android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE, 95 150, 10, 250, 20, 0); 96 97 NetworkStatsHistory history1 = new NetworkStatsHistory(10, 2); 98 history1.recordData(10, 20, uid1Entry1); 99 history1.recordData(20, 30, uid1Entry2); 100 101 NetworkStatsHistory history2 = new NetworkStatsHistory(10, 2); 102 history1.recordData(30, 40, uid2Entry1); 103 history1.recordData(35, 45, uid2Entry2); 104 105 106 when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession); 107 when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2, uid3 }); 108 109 when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class), 110 eq(uid1), eq(android.net.NetworkStats.SET_ALL), 111 eq(android.net.NetworkStats.TAG_NONE), 112 eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime))) 113 .then((InvocationOnMock inv) -> { 114 NetworkTemplate template = inv.getArgument(0); 115 assertEquals(MATCH_MOBILE_ALL, template.getMatchRule()); 116 assertEquals(subscriberId, template.getSubscriberId()); 117 return history1; 118 }); 119 120 when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class), 121 eq(uid2), eq(android.net.NetworkStats.SET_ALL), 122 eq(android.net.NetworkStats.TAG_NONE), 123 eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime))) 124 .then((InvocationOnMock inv) -> { 125 NetworkTemplate template = inv.getArgument(0); 126 assertEquals(MATCH_MOBILE_ALL, template.getMatchRule()); 127 assertEquals(subscriberId, template.getSubscriberId()); 128 return history2; 129 }); 130 131 132 NetworkStats stats = mManager.queryDetails( 133 ConnectivityManager.TYPE_MOBILE, subscriberId, startTime, endTime); 134 135 NetworkStats.Bucket bucket = new NetworkStats.Bucket(); 136 137 // First 2 buckets exactly match entry timings 138 assertTrue(stats.getNextBucket(bucket)); 139 assertEquals(10, bucket.getStartTimeStamp()); 140 assertEquals(20, bucket.getEndTimeStamp()); 141 assertBucketMatches(uid1Entry1, bucket); 142 143 assertTrue(stats.getNextBucket(bucket)); 144 assertEquals(20, bucket.getStartTimeStamp()); 145 assertEquals(30, bucket.getEndTimeStamp()); 146 assertBucketMatches(uid1Entry2, bucket); 147 148 // 30 -> 40: contains uid2Entry1 and half of uid2Entry2 149 assertTrue(stats.getNextBucket(bucket)); 150 assertEquals(30, bucket.getStartTimeStamp()); 151 assertEquals(40, bucket.getEndTimeStamp()); 152 assertEquals(225, bucket.getRxBytes()); 153 assertEquals(15, bucket.getRxPackets()); 154 assertEquals(375, bucket.getTxBytes()); 155 assertEquals(30, bucket.getTxPackets()); 156 157 // 40 -> 50: contains half of uid2Entry2 158 assertTrue(stats.getNextBucket(bucket)); 159 assertEquals(40, bucket.getStartTimeStamp()); 160 assertEquals(50, bucket.getEndTimeStamp()); 161 assertEquals(75, bucket.getRxBytes()); 162 assertEquals(5, bucket.getRxPackets()); 163 assertEquals(125, bucket.getTxBytes()); 164 assertEquals(10, bucket.getTxPackets()); 165 166 assertFalse(stats.hasNextBucket()); 167 } 168 169 @Test 170 public void testQueryDetails_NoSubscriberId() throws RemoteException { 171 final long startTime = 1; 172 final long endTime = 100; 173 final int uid1 = 10001; 174 final int uid2 = 10002; 175 176 when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession); 177 when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2 }); 178 179 NetworkStats stats = mManager.queryDetails( 180 ConnectivityManager.TYPE_MOBILE, null, startTime, endTime); 181 182 when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class), 183 anyInt(), anyInt(), anyInt(), anyInt(), anyLong(), anyLong())) 184 .thenReturn(new NetworkStatsHistory(10, 0)); 185 186 verify(mStatsSession, times(1)).getHistoryIntervalForUid( 187 argThat((NetworkTemplate t) -> 188 // No subscriberId: MATCH_MOBILE_WILDCARD template 189 t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD), 190 eq(uid1), eq(android.net.NetworkStats.SET_ALL), 191 eq(android.net.NetworkStats.TAG_NONE), 192 eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)); 193 194 verify(mStatsSession, times(1)).getHistoryIntervalForUid( 195 argThat((NetworkTemplate t) -> 196 // No subscriberId: MATCH_MOBILE_WILDCARD template 197 t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD), 198 eq(uid2), eq(android.net.NetworkStats.SET_ALL), 199 eq(android.net.NetworkStats.TAG_NONE), 200 eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)); 201 202 assertFalse(stats.hasNextBucket()); 203 } 204 205 private void assertBucketMatches(Entry expected, 206 NetworkStats.Bucket actual) { 207 assertEquals(expected.uid, actual.getUid()); 208 assertEquals(expected.rxBytes, actual.getRxBytes()); 209 assertEquals(expected.rxPackets, actual.getRxPackets()); 210 assertEquals(expected.txBytes, actual.getTxBytes()); 211 assertEquals(expected.txPackets, actual.getTxPackets()); 212 } 213 } 214