Merge "Allow null subscriberId in NetworkStatsManager."
This commit is contained in:
@@ -24,7 +24,6 @@ import android.net.NetworkStatsHistory;
|
||||
import android.net.NetworkTemplate;
|
||||
import android.net.TrafficStats;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.IntArray;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -98,9 +97,8 @@ public final class NetworkStats implements AutoCloseable {
|
||||
|
||||
/** @hide */
|
||||
NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp,
|
||||
long endTimestamp) throws RemoteException, SecurityException {
|
||||
final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
||||
long endTimestamp, INetworkStatsService statsService)
|
||||
throws RemoteException, SecurityException {
|
||||
// Open network stats session
|
||||
mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName());
|
||||
mCloseGuard.open("close");
|
||||
|
||||
@@ -37,6 +37,8 @@ import android.os.ServiceManager;
|
||||
import android.os.ServiceManager.ServiceNotFoundException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* Provides access to network usage history and statistics. Usage data is collected in
|
||||
* discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
|
||||
@@ -107,9 +109,15 @@ public class NetworkStatsManager {
|
||||
* {@hide}
|
||||
*/
|
||||
public NetworkStatsManager(Context context) throws ServiceNotFoundException {
|
||||
this(context, INetworkStatsService.Stub.asInterface(
|
||||
ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public NetworkStatsManager(Context context, INetworkStatsService service) {
|
||||
mContext = context;
|
||||
mService = INetworkStatsService.Stub.asInterface(
|
||||
ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE));
|
||||
mService = service;
|
||||
setPollOnOpen(true);
|
||||
}
|
||||
|
||||
@@ -135,7 +143,8 @@ public class NetworkStatsManager {
|
||||
public Bucket querySummaryForDevice(NetworkTemplate template,
|
||||
long startTime, long endTime) throws SecurityException, RemoteException {
|
||||
Bucket bucket = null;
|
||||
NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime);
|
||||
NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
|
||||
mService);
|
||||
bucket = stats.getDeviceSummaryForNetwork();
|
||||
|
||||
stats.close();
|
||||
@@ -208,7 +217,7 @@ public class NetworkStatsManager {
|
||||
}
|
||||
|
||||
NetworkStats stats;
|
||||
stats = new NetworkStats(mContext, template, mFlags, startTime, endTime);
|
||||
stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
|
||||
stats.startSummaryEnumeration();
|
||||
|
||||
stats.close();
|
||||
@@ -245,7 +254,7 @@ public class NetworkStatsManager {
|
||||
}
|
||||
|
||||
NetworkStats result;
|
||||
result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
|
||||
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
|
||||
result.startSummaryEnumeration();
|
||||
|
||||
return result;
|
||||
@@ -295,7 +304,7 @@ public class NetworkStatsManager {
|
||||
|
||||
NetworkStats result;
|
||||
try {
|
||||
result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
|
||||
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
|
||||
result.startHistoryEnumeration(uid, tag);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e);
|
||||
@@ -341,7 +350,7 @@ public class NetworkStatsManager {
|
||||
}
|
||||
|
||||
NetworkStats result;
|
||||
result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
|
||||
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
|
||||
result.startUserUidEnumeration();
|
||||
return result;
|
||||
}
|
||||
@@ -451,19 +460,20 @@ public class NetworkStatsManager {
|
||||
}
|
||||
|
||||
private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
|
||||
NetworkTemplate template = null;
|
||||
final NetworkTemplate template;
|
||||
switch (networkType) {
|
||||
case ConnectivityManager.TYPE_MOBILE: {
|
||||
template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
|
||||
} break;
|
||||
case ConnectivityManager.TYPE_WIFI: {
|
||||
case ConnectivityManager.TYPE_MOBILE:
|
||||
template = subscriberId == null
|
||||
? NetworkTemplate.buildTemplateMobileWildcard()
|
||||
: NetworkTemplate.buildTemplateMobileAll(subscriberId);
|
||||
break;
|
||||
case ConnectivityManager.TYPE_WIFI:
|
||||
template = NetworkTemplate.buildTemplateWifiWildcard();
|
||||
} break;
|
||||
default: {
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Cannot create template for network type "
|
||||
+ networkType + ", subscriberId '"
|
||||
+ NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
|
||||
}
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
||||
213
tests/net/java/android/app/usage/NetworkStatsManagerTest.java
Normal file
213
tests/net/java/android/app/usage/NetworkStatsManagerTest.java
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user