Merge "Make addUnwantedCapability method public" into pi-dev
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index e07f586..80b1c3d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -861,6 +861,10 @@
* You should always check {@link NetworkInfo#isConnected()} before initiating
* network traffic. This may return {@code null} when there is no default
* network.
+ * Note that if the default network is a VPN, this method will return the
+ * NetworkInfo for one of its underlying networks instead, or null if the
+ * VPN agent did not specify any. Apps interested in learning about VPNs
+ * should use {@link #getNetworkInfo(android.net.Network)} instead.
*
* @return a {@link NetworkInfo} object for the current default network
* or {@code null} if no default network is currently active
@@ -1018,7 +1022,11 @@
* which you're interested.
* @return a {@link NetworkInfo} object for the requested
* network type or {@code null} if the type is not
- * supported by the device.
+ * supported by the device. If {@code networkType} is
+ * TYPE_VPN and a VPN is active for the calling app,
+ * then this method will try to return one of the
+ * underlying networks for the VPN or null if the
+ * VPN agent didn't specify any.
*
* @deprecated This method does not support multiple connected networks
* of the same type. Use {@link #getAllNetworks} and
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 5df168d..15a0ee5 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -26,6 +26,8 @@
import com.android.okhttp.internalandroidapi.Dns;
import com.android.okhttp.internalandroidapi.HttpURLConnectionFactory;
+import libcore.io.IoUtils;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.DatagramSocket;
@@ -77,6 +79,11 @@
httpKeepAlive ? Integer.parseInt(System.getProperty("http.maxConnections", "5")) : 0;
private static final long httpKeepAliveDurationMs =
Long.parseLong(System.getProperty("http.keepAliveDuration", "300000")); // 5 minutes.
+ // Value used to obfuscate network handle longs.
+ // The HANDLE_MAGIC value MUST be kept in sync with the corresponding
+ // value in the native/android/net.c NDK implementation.
+ private static final long HANDLE_MAGIC = 0xcafed00dL;
+ private static final int HANDLE_MAGIC_SIZE = 32;
/**
* @hide
@@ -137,9 +144,15 @@
for (int i = 0; i < hostAddresses.length; i++) {
try {
Socket socket = createSocket();
- if (localAddress != null) socket.bind(localAddress);
- socket.connect(new InetSocketAddress(hostAddresses[i], port));
- return socket;
+ boolean failed = true;
+ try {
+ if (localAddress != null) socket.bind(localAddress);
+ socket.connect(new InetSocketAddress(hostAddresses[i], port));
+ failed = false;
+ return socket;
+ } finally {
+ if (failed) IoUtils.closeQuietly(socket);
+ }
} catch (IOException e) {
if (i == (hostAddresses.length - 1)) throw e;
}
@@ -156,15 +169,27 @@
public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
int localPort) throws IOException {
Socket socket = createSocket();
- socket.bind(new InetSocketAddress(localAddress, localPort));
- socket.connect(new InetSocketAddress(address, port));
+ boolean failed = true;
+ try {
+ socket.bind(new InetSocketAddress(localAddress, localPort));
+ socket.connect(new InetSocketAddress(address, port));
+ failed = false;
+ } finally {
+ if (failed) IoUtils.closeQuietly(socket);
+ }
return socket;
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
Socket socket = createSocket();
- socket.connect(new InetSocketAddress(host, port));
+ boolean failed = true;
+ try {
+ socket.connect(new InetSocketAddress(host, port));
+ failed = false;
+ } finally {
+ if (failed) IoUtils.closeQuietly(socket);
+ }
return socket;
}
@@ -176,7 +201,13 @@
@Override
public Socket createSocket() throws IOException {
Socket socket = new Socket();
- bindSocket(socket);
+ boolean failed = true;
+ try {
+ bindSocket(socket);
+ failed = false;
+ } finally {
+ if (failed) IoUtils.closeQuietly(socket);
+ }
return socket;
}
}
@@ -335,6 +366,25 @@
}
/**
+ * Returns a {@link Network} object given a handle returned from {@link #getNetworkHandle}.
+ *
+ * @param networkHandle a handle returned from {@link #getNetworkHandle}.
+ * @return A {@link Network} object derived from {@code networkHandle}.
+ */
+ public static Network fromNetworkHandle(long networkHandle) {
+ if (networkHandle == 0) {
+ throw new IllegalArgumentException(
+ "Network.fromNetworkHandle refusing to instantiate NETID_UNSET Network.");
+ }
+ if ((networkHandle & ((1L << HANDLE_MAGIC_SIZE) - 1)) != HANDLE_MAGIC
+ || networkHandle < 0) {
+ throw new IllegalArgumentException(
+ "Value passed to fromNetworkHandle() is not a network handle.");
+ }
+ return new Network((int) (networkHandle >> HANDLE_MAGIC_SIZE));
+ }
+
+ /**
* Returns a handle representing this {@code Network}, for use with the NDK API.
*/
public long getNetworkHandle() {
@@ -356,14 +406,10 @@
// At some future date it may be desirable to realign the handle with
// Multiple Provisioning Domains API recommendations, as made by the
// IETF mif working group.
- //
- // The handleMagic value MUST be kept in sync with the corresponding
- // value in the native/android/net.c NDK implementation.
if (netId == 0) {
return 0L; // make this zero condition obvious for debugging
}
- final long handleMagic = 0xcafed00dL;
- return (((long) netId) << 32) | handleMagic;
+ return (((long) netId) << HANDLE_MAGIC_SIZE) | HANDLE_MAGIC;
}
// implement the Parcelable interface
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index ff5714b..374b3ab 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.IntDef;
+import android.annotation.SystemApi;
import android.net.ConnectivityManager.NetworkCallback;
import android.os.Parcel;
import android.os.Parcelable;
@@ -276,6 +277,7 @@
* this network can be used by system apps to upload telemetry data.
* @hide
*/
+ @SystemApi
public static final int NET_CAPABILITY_OEM_PAID = 22;
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 7a42518..3d9d6e2 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -17,6 +17,8 @@
package android.net;
import android.annotation.NonNull;
+import android.net.NetworkCapabilities.NetCapability;
+import android.net.NetworkCapabilities.Transport;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
@@ -426,6 +428,20 @@
return type == Type.BACKGROUND_REQUEST;
}
+ /**
+ * @see Builder#addCapability(int)
+ */
+ public boolean hasCapability(@NetCapability int capability) {
+ return networkCapabilities.hasCapability(capability);
+ }
+
+ /**
+ * @see Builder#addTransportType(int)
+ */
+ public boolean hasTransport(@Transport int transportType) {
+ return networkCapabilities.hasTransport(transportType);
+ }
+
public String toString() {
return "NetworkRequest [ " + type + " id=" + requestId +
(legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 91d3afb..861ae83 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -5320,7 +5320,6 @@
for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
final String stackedIface = stacked.getInterfaceName();
bs.noteNetworkInterfaceType(stackedIface, type);
- NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
}
} catch (RemoteException ignored) {
}
diff --git a/tests/net/java/android/app/usage/NetworkStatsManagerTest.java b/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
new file mode 100644
index 0000000..25e1474
--- /dev/null
+++ b/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
@@ -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());
+ }
+}
diff --git a/tests/net/java/android/net/IpSecAlgorithmTest.java b/tests/net/java/android/net/IpSecAlgorithmTest.java
index 6bdfdc6..85e8361 100644
--- a/tests/net/java/android/net/IpSecAlgorithmTest.java
+++ b/tests/net/java/android/net/IpSecAlgorithmTest.java
@@ -22,8 +22,12 @@
import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+
+import java.util.AbstractMap.SimpleEntry;
import java.util.Arrays;
+import java.util.Map.Entry;
import java.util.Random;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,19 +44,29 @@
};
@Test
- public void testDefaultTruncLen() throws Exception {
- IpSecAlgorithm explicit =
+ public void testNoTruncLen() throws Exception {
+ Entry<String, Integer>[] authAndAeadList =
+ new Entry[] {
+ new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_MD5, 128),
+ new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA1, 160),
+ new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA256, 256),
+ new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA384, 384),
+ new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA512, 512),
+ new SimpleEntry<>(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, 224)
+ };
+
+ // Expect auth and aead algorithms to throw errors if trunclen is omitted.
+ for (Entry<String, Integer> algData : authAndAeadList) {
+ try {
new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA256, Arrays.copyOf(KEY_MATERIAL, 256 / 8), 256);
- IpSecAlgorithm implicit =
- new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA256, Arrays.copyOf(KEY_MATERIAL, 256 / 8));
- assertTrue(
- "Default Truncation Length Incorrect, Explicit: "
- + explicit
- + "implicit: "
- + implicit,
- IpSecAlgorithm.equals(explicit, implicit));
+ algData.getKey(), Arrays.copyOf(KEY_MATERIAL, algData.getValue() / 8));
+ fail("Expected exception on unprovided auth trunclen");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ // Ensure crypt works with no truncation length supplied.
+ new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, 256 / 8));
}
@Test
diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/tests/net/java/android/net/IpSecConfigTest.java
index f186ee5..771faaf 100644
--- a/tests/net/java/android/net/IpSecConfigTest.java
+++ b/tests/net/java/android/net/IpSecConfigTest.java
@@ -62,7 +62,8 @@
c.setAuthentication(
new IpSecAlgorithm(
IpSecAlgorithm.AUTH_HMAC_MD5,
- new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0}));
+ new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0},
+ 128));
c.setAuthenticatedEncryption(
new IpSecAlgorithm(
IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
index 0ca20de..970596d 100644
--- a/tests/net/java/android/net/IpSecManagerTest.java
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -179,7 +179,7 @@
IpSecManager.UdpEncapsulationSocket encapSocket =
mIpSecManager.openUdpEncapsulationSocket(TEST_UDP_ENCAP_PORT);
- assertNotNull(encapSocket.getSocket());
+ assertNotNull(encapSocket.getFileDescriptor());
assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
encapSocket.close();
@@ -202,7 +202,7 @@
IpSecManager.UdpEncapsulationSocket encapSocket =
mIpSecManager.openUdpEncapsulationSocket();
- assertNotNull(encapSocket.getSocket());
+ assertNotNull(encapSocket.getFileDescriptor());
assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
encapSocket.close();
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index 035a4cd..0530a86 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -19,6 +19,7 @@
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
+import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
@@ -31,6 +32,7 @@
import static android.net.NetworkStats.SET_DBG_VPN_OUT;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static org.junit.Assert.assertEquals;
@@ -641,6 +643,136 @@
ROAMING_ALL, DEFAULT_NETWORK_ALL, 50500L, 27L, 100200L, 55, 0);
}
+ @Test
+ public void testFilter_NoFilter() {
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 3)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3);
+
+ stats.filter(UID_ALL, INTERFACES_ALL, TAG_ALL);
+ assertEquals(3, stats.size());
+ assertEquals(entry1, stats.getValues(0, null));
+ assertEquals(entry2, stats.getValues(1, null));
+ assertEquals(entry3, stats.getValues(2, null));
+ }
+
+ @Test
+ public void testFilter_UidFilter() {
+ final int testUid = 10101;
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "test2", testUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test2", testUid, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 3)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3);
+
+ stats.filter(testUid, INTERFACES_ALL, TAG_ALL);
+ assertEquals(2, stats.size());
+ assertEquals(entry2, stats.getValues(0, null));
+ assertEquals(entry3, stats.getValues(1, null));
+ }
+
+ @Test
+ public void testFilter_InterfaceFilter() {
+ final String testIf1 = "testif1";
+ final String testIf2 = "testif2";
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ testIf1, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "otherif", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ testIf1, 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry4 = new NetworkStats.Entry(
+ testIf2, 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 4)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3)
+ .addValues(entry4);
+
+ stats.filter(UID_ALL, new String[] { testIf1, testIf2 }, TAG_ALL);
+ assertEquals(3, stats.size());
+ assertEquals(entry1, stats.getValues(0, null));
+ assertEquals(entry3, stats.getValues(1, null));
+ assertEquals(entry4, stats.getValues(2, null));
+ }
+
+ @Test
+ public void testFilter_EmptyInterfaceFilter() {
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "if1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "if2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 3)
+ .addValues(entry1)
+ .addValues(entry2);
+
+ stats.filter(UID_ALL, new String[] { }, TAG_ALL);
+ assertEquals(0, stats.size());
+ }
+
+ @Test
+ public void testFilter_TagFilter() {
+ final int testTag = 123;
+ final int otherTag = 456;
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "test1", 10100, SET_DEFAULT, testTag, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, testTag, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, otherTag, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 3)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3);
+
+ stats.filter(UID_ALL, INTERFACES_ALL, testTag);
+ assertEquals(2, stats.size());
+ assertEquals(entry1, stats.getValues(0, null));
+ assertEquals(entry2, stats.getValues(1, null));
+ }
+
private static void assertContains(NetworkStats stats, String iface, int uid, int set,
int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
long txBytes, long txPackets, long operations) {
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index b14f550..fc46b9c 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -184,7 +184,7 @@
assertStatsEntry(stats, "dummy0", 0, SET_DEFAULT, 0x0, 0L, 168L);
assertStatsEntry(stats, "lo", 0, SET_DEFAULT, 0x0, 1288L, 1288L);
- NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
+ NetworkStatsFactory.clearStackedIfaces();
}
@Test
@@ -212,7 +212,7 @@
assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesAfter, 7867488L);
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesAfter, 647587L);
- NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
+ NetworkStatsFactory.clearStackedIfaces();
}
/**
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 4a83d1b..f025f41 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -26,6 +26,8 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -62,8 +64,8 @@
private void expectPermission(String[] permissions, boolean preinstalled) throws Exception {
final PackageInfo packageInfo = packageInfoWithPermissions(permissions, preinstalled);
- when(mPackageManager.getPackageInfo(MOCK_PACKAGE_NAMES[0], GET_PERMISSIONS))
- .thenReturn(packageInfo);
+ when(mPackageManager.getPackageInfoAsUser(
+ eq(MOCK_PACKAGE_NAMES[0]), eq(GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
}
private PackageInfo packageInfoWithPermissions(String[] permissions, boolean preinstalled) {
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index f59850d..e377a47 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -70,6 +70,7 @@
import android.os.Bundle;
import android.os.INetworkManagementService;
import android.os.Looper;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.test.filters.SmallTest;
@@ -88,6 +89,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.net.Inet4Address;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -639,4 +642,32 @@
lp.addRoute(new RouteInfo(new IpPrefix("::/1")));
assertTrue(Vpn.providesRoutesToMostDestinations(lp));
}
+
+ @Test
+ public void testDoesNotLockUpWithTooManyRoutes() {
+ final LinkProperties lp = new LinkProperties();
+ final byte[] ad = new byte[4];
+ // Actually evaluating this many routes under 1500ms is impossible on
+ // current hardware and for some time, as the algorithm is O(n²).
+ // Make sure the system has a safeguard against this and does not
+ // lock up.
+ final int MAX_ROUTES = 4000;
+ final long MAX_ALLOWED_TIME_MS = 1500;
+ for (int i = 0; i < MAX_ROUTES; ++i) {
+ ad[0] = (byte)((i >> 24) & 0xFF);
+ ad[1] = (byte)((i >> 16) & 0xFF);
+ ad[2] = (byte)((i >> 8) & 0xFF);
+ ad[3] = (byte)(i & 0xFF);
+ try {
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.getByAddress(ad), 32)));
+ } catch (UnknownHostException e) {
+ // UnknownHostException is only thrown for an address of illegal length,
+ // which can't happen in the case above.
+ }
+ }
+ final long start = SystemClock.currentThreadTimeMillis();
+ assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+ final long end = SystemClock.currentThreadTimeMillis();
+ assertTrue(end - start < MAX_ALLOWED_TIME_MS);
+ }
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 49b2643..e371abc 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -25,6 +25,7 @@
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
@@ -58,6 +59,9 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -94,6 +98,7 @@
import android.telephony.TelephonyManager;
import com.android.internal.net.VpnInfo;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.server.LocalServices;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
@@ -652,6 +657,94 @@
}
@Test
+ public void testDetailedUidStats() throws Exception {
+ // pretend that network comes online
+ expectDefaultSettings();
+ expectNetworkState(buildWifiState());
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(NETWORKS_WIFI);
+
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L);
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 50L, 5L, 50L, 5L, 0L);
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xBEEF, 1024L, 8L, 512L, 4L, 0L);
+
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3));
+ mService.incrementOperationCount(UID_RED, 0xF00D, 1);
+
+ NetworkStats stats = mService.getDetailedUidStats(INTERFACES_ALL);
+
+ assertEquals(3, stats.size());
+ entry1.operations = 1;
+ assertEquals(entry1, stats.getValues(0, null));
+ entry2.operations = 1;
+ assertEquals(entry2, stats.getValues(1, null));
+ assertEquals(entry3, stats.getValues(2, null));
+ }
+
+ @Test
+ public void testDetailedUidStats_Filtered() throws Exception {
+ // pretend that network comes online
+ expectDefaultSettings();
+
+ final String stackedIface = "stacked-test0";
+ final LinkProperties stackedProp = new LinkProperties();
+ stackedProp.setInterfaceName(stackedIface);
+ final NetworkState wifiState = buildWifiState();
+ wifiState.linkProperties.addStackedLink(stackedProp);
+ expectNetworkState(wifiState);
+
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(NETWORKS_WIFI);
+
+ NetworkStats.Entry uidStats = new NetworkStats.Entry(
+ TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
+ // Stacked on matching interface
+ NetworkStats.Entry tetheredStats1 = new NetworkStats.Entry(
+ stackedIface, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
+ // Different interface
+ NetworkStats.Entry tetheredStats2 = new NetworkStats.Entry(
+ "otherif", UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
+
+ final String[] ifaceFilter = new String[] { TEST_IFACE };
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(buildEmptyStats());
+ when(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL), any()))
+ .thenReturn(new NetworkStats(getElapsedRealtime(), 1)
+ .addValues(uidStats));
+ when(mNetManager.getNetworkStatsTethering(STATS_PER_UID))
+ .thenReturn(new NetworkStats(getElapsedRealtime(), 2)
+ .addValues(tetheredStats1)
+ .addValues(tetheredStats2));
+
+ NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
+
+ verify(mNetManager, times(1)).getNetworkStatsUidDetail(eq(UID_ALL), argThat(ifaces ->
+ ifaces != null && ifaces.length == 2
+ && ArrayUtils.contains(ifaces, TEST_IFACE)
+ && ArrayUtils.contains(ifaces, stackedIface)));
+
+ assertEquals(2, stats.size());
+ assertEquals(uidStats, stats.getValues(0, null));
+ assertEquals(tetheredStats1, stats.getValues(1, null));
+ }
+
+ @Test
public void testForegroundBackground() throws Exception {
// pretend that network comes online
expectDefaultSettings();
@@ -1027,7 +1120,7 @@
private void expectNetworkStatsUidDetail(NetworkStats detail, NetworkStats tetherStats)
throws Exception {
- when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail);
+ when(mNetManager.getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL)).thenReturn(detail);
// also include tethering details, since they are folded into UID
when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)).thenReturn(tetherStats);