blob: 25e147416d2c2964a4950dc9e2b16cb3f47dc648 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.usage;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
import android.net.NetworkStats.Entry;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class NetworkStatsManagerTest {
private @Mock INetworkStatsService mService;
private @Mock INetworkStatsSession mStatsSession;
private NetworkStatsManager mManager;
// TODO: change to NetworkTemplate.MATCH_MOBILE once internal constant rename is merged to aosp.
private static final int MATCH_MOBILE_ALL = 1;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mManager = new NetworkStatsManager(InstrumentationRegistry.getContext(), mService);
}
@Test
public void testQueryDetails() throws RemoteException {
final String subscriberId = "subid";
final long startTime = 1;
final long endTime = 100;
final int uid1 = 10001;
final int uid2 = 10002;
final int uid3 = 10003;
Entry uid1Entry1 = new Entry("if1", uid1,
android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
100, 10, 200, 20, 0);
Entry uid1Entry2 = new Entry(
"if2", uid1,
android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
100, 10, 200, 20, 0);
Entry uid2Entry1 = new Entry("if1", uid2,
android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
150, 10, 250, 20, 0);
Entry uid2Entry2 = new Entry(
"if2", uid2,
android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
150, 10, 250, 20, 0);
NetworkStatsHistory history1 = new NetworkStatsHistory(10, 2);
history1.recordData(10, 20, uid1Entry1);
history1.recordData(20, 30, uid1Entry2);
NetworkStatsHistory history2 = new NetworkStatsHistory(10, 2);
history1.recordData(30, 40, uid2Entry1);
history1.recordData(35, 45, uid2Entry2);
when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession);
when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2, uid3 });
when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
eq(uid1), eq(android.net.NetworkStats.SET_ALL),
eq(android.net.NetworkStats.TAG_NONE),
eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)))
.then((InvocationOnMock inv) -> {
NetworkTemplate template = inv.getArgument(0);
assertEquals(MATCH_MOBILE_ALL, template.getMatchRule());
assertEquals(subscriberId, template.getSubscriberId());
return history1;
});
when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
eq(uid2), eq(android.net.NetworkStats.SET_ALL),
eq(android.net.NetworkStats.TAG_NONE),
eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)))
.then((InvocationOnMock inv) -> {
NetworkTemplate template = inv.getArgument(0);
assertEquals(MATCH_MOBILE_ALL, template.getMatchRule());
assertEquals(subscriberId, template.getSubscriberId());
return history2;
});
NetworkStats stats = mManager.queryDetails(
ConnectivityManager.TYPE_MOBILE, subscriberId, startTime, endTime);
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
// First 2 buckets exactly match entry timings
assertTrue(stats.getNextBucket(bucket));
assertEquals(10, bucket.getStartTimeStamp());
assertEquals(20, bucket.getEndTimeStamp());
assertBucketMatches(uid1Entry1, bucket);
assertTrue(stats.getNextBucket(bucket));
assertEquals(20, bucket.getStartTimeStamp());
assertEquals(30, bucket.getEndTimeStamp());
assertBucketMatches(uid1Entry2, bucket);
// 30 -> 40: contains uid2Entry1 and half of uid2Entry2
assertTrue(stats.getNextBucket(bucket));
assertEquals(30, bucket.getStartTimeStamp());
assertEquals(40, bucket.getEndTimeStamp());
assertEquals(225, bucket.getRxBytes());
assertEquals(15, bucket.getRxPackets());
assertEquals(375, bucket.getTxBytes());
assertEquals(30, bucket.getTxPackets());
// 40 -> 50: contains half of uid2Entry2
assertTrue(stats.getNextBucket(bucket));
assertEquals(40, bucket.getStartTimeStamp());
assertEquals(50, bucket.getEndTimeStamp());
assertEquals(75, bucket.getRxBytes());
assertEquals(5, bucket.getRxPackets());
assertEquals(125, bucket.getTxBytes());
assertEquals(10, bucket.getTxPackets());
assertFalse(stats.hasNextBucket());
}
@Test
public void testQueryDetails_NoSubscriberId() throws RemoteException {
final long startTime = 1;
final long endTime = 100;
final int uid1 = 10001;
final int uid2 = 10002;
when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession);
when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2 });
NetworkStats stats = mManager.queryDetails(
ConnectivityManager.TYPE_MOBILE, null, startTime, endTime);
when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
anyInt(), anyInt(), anyInt(), anyInt(), anyLong(), anyLong()))
.thenReturn(new NetworkStatsHistory(10, 0));
verify(mStatsSession, times(1)).getHistoryIntervalForUid(
argThat((NetworkTemplate t) ->
// No subscriberId: MATCH_MOBILE_WILDCARD template
t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD),
eq(uid1), eq(android.net.NetworkStats.SET_ALL),
eq(android.net.NetworkStats.TAG_NONE),
eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime));
verify(mStatsSession, times(1)).getHistoryIntervalForUid(
argThat((NetworkTemplate t) ->
// No subscriberId: MATCH_MOBILE_WILDCARD template
t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD),
eq(uid2), eq(android.net.NetworkStats.SET_ALL),
eq(android.net.NetworkStats.TAG_NONE),
eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime));
assertFalse(stats.hasNextBucket());
}
private void assertBucketMatches(Entry expected,
NetworkStats.Bucket actual) {
assertEquals(expected.uid, actual.getUid());
assertEquals(expected.rxBytes, actual.getRxBytes());
assertEquals(expected.rxPackets, actual.getRxPackets());
assertEquals(expected.txBytes, actual.getTxBytes());
assertEquals(expected.txPackets, actual.getTxPackets());
}
}