Merge "Clean up the keepalive slots when network disconnect"
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 0e10de8..a69ca99 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3449,6 +3449,10 @@
final NetworkCallback callback;
synchronized (sCallbacks) {
callback = sCallbacks.get(request);
+ if (message.what == CALLBACK_UNAVAIL) {
+ sCallbacks.remove(request);
+ callback.networkRequest = ALREADY_UNREGISTERED;
+ }
}
if (DBG) {
Log.d(TAG, getCallbackName(message.what) + " for network " + network);
@@ -3995,8 +3999,10 @@
synchronized (sCallbacks) {
Preconditions.checkArgument(networkCallback.networkRequest != null,
"NetworkCallback was not registered");
- Preconditions.checkArgument(networkCallback.networkRequest != ALREADY_UNREGISTERED,
- "NetworkCallback was already unregistered");
+ if (networkCallback.networkRequest == ALREADY_UNREGISTERED) {
+ Log.d(TAG, "NetworkCallback was already unregistered");
+ return;
+ }
for (Map.Entry<NetworkRequest, NetworkCallback> e : sCallbacks.entrySet()) {
if (e.getValue() == networkCallback) {
reqs.add(e.getKey());
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 28c59db..c5fc9b3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -49,8 +49,8 @@
namespace android {
constexpr int MAXPACKETSIZE = 8 * 1024;
-// FrameworkListener limits the size of commands to 1024 bytes. TODO: fix this.
-constexpr int MAXCMDSIZE = 1024;
+// FrameworkListener limits the size of commands to 4096 bytes.
+constexpr int MAXCMDSIZE = 4096;
static void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 90c86c7..63fd2fd 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2861,7 +2861,7 @@
try {
nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
// With Private DNS bypass support, we can proceed to update the
@@ -3031,7 +3031,7 @@
try {
nai.networkMonitor().notifyNetworkDisconnected();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
mNetworkAgentInfos.remove(nai.messenger);
nai.clatd.update();
@@ -3070,11 +3070,7 @@
// fallback network the default or requested a new network from the
// NetworkFactories, so network traffic isn't interrupted for an unnecessarily
// long time.
- try {
- mNetd.networkDestroy(nai.network.netId);
- } catch (RemoteException | ServiceSpecificException e) {
- loge("Exception destroying network: " + e);
- }
+ destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network);
}
synchronized (mNetworkForNetId) {
@@ -3082,6 +3078,35 @@
}
}
+ private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+ try {
+ // This should never fail. Specifying an already in use NetID will cause failure.
+ if (networkAgent.isVPN()) {
+ mNetd.networkCreateVpn(networkAgent.network.netId,
+ (networkAgent.networkMisc == null
+ || !networkAgent.networkMisc.allowBypass));
+ } else {
+ mNetd.networkCreatePhysical(networkAgent.network.netId,
+ getNetworkPermission(networkAgent.networkCapabilities));
+ }
+ mDnsResolver.createNetworkCache(networkAgent.network.netId);
+ return true;
+ } catch (RemoteException | ServiceSpecificException e) {
+ loge("Error creating network " + networkAgent.network.netId + ": "
+ + e.getMessage());
+ return false;
+ }
+ }
+
+ private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+ try {
+ mNetd.networkDestroy(networkAgent.network.netId);
+ mDnsResolver.destroyNetworkCache(networkAgent.network.netId);
+ } catch (RemoteException | ServiceSpecificException e) {
+ loge("Exception destroying network: " + e);
+ }
+ }
+
// If this method proves to be too slow then we can maintain a separate
// pendingIntent => NetworkRequestInfo map.
// This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
@@ -3420,7 +3445,7 @@
try {
nai.networkMonitor().setAcceptPartialConnectivity();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
}
}
@@ -3456,7 +3481,7 @@
try {
nai.networkMonitor().launchCaptivePortalApp();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
});
}
@@ -4084,7 +4109,7 @@
try {
nai.networkMonitor().forceReevaluation(uid);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
}
@@ -5464,7 +5489,7 @@
try {
networkMonitor.start();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
NetworkInfo networkInfo = nai.networkInfo;
@@ -5521,7 +5546,7 @@
try {
networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
if (networkAgent.everConnected) {
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
@@ -6482,21 +6507,7 @@
// A network that has just connected has zero requests and is thus a foreground network.
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
- try {
- // This should never fail. Specifying an already in use NetID will cause failure.
- if (networkAgent.isVPN()) {
- mNMS.createVirtualNetwork(networkAgent.network.netId,
- (networkAgent.networkMisc == null ||
- !networkAgent.networkMisc.allowBypass));
- } else {
- mNMS.createPhysicalNetwork(networkAgent.network.netId,
- getNetworkPermission(networkAgent.networkCapabilities));
- }
- } catch (Exception e) {
- loge("Error creating network " + networkAgent.network.netId + ": "
- + e.getMessage());
- return;
- }
+ if (!createNativeNetwork(networkAgent)) return;
networkAgent.created = true;
}
@@ -6527,7 +6538,7 @@
networkAgent.networkMonitor().notifyNetworkConnected(
networkAgent.linkProperties, networkAgent.networkCapabilities);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
scheduleUnvalidatedPrompt(networkAgent);
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index e33392d..2321afb 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -263,12 +263,6 @@
}
public void removeNetwork(Network network) {
- try {
- mDnsResolver.clearResolverConfiguration(network.netId);
- } catch (RemoteException | ServiceSpecificException e) {
- Slog.e(TAG, "Error clearing DNS configuration: " + e);
- return;
- }
mPrivateDnsMap.remove(network.netId);
mPrivateDnsValidationMap.remove(network.netId);
}
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/services/net/java/android/net/NattKeepalivePacketData.java
similarity index 84%
rename from core/java/android/net/NattKeepalivePacketData.java
rename to services/net/java/android/net/NattKeepalivePacketData.java
index bdb246f..27ed11e 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/services/net/java/android/net/NattKeepalivePacketData.java
@@ -19,8 +19,10 @@
import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
+import android.annotation.NonNull;
import android.net.SocketKeepalive.InvalidPacketException;
import android.net.util.IpUtils;
+import android.os.Parcelable;
import android.system.OsConstants;
import java.net.Inet4Address;
@@ -29,8 +31,7 @@
import java.nio.ByteOrder;
/** @hide */
-public final class NattKeepalivePacketData extends KeepalivePacketData {
-
+public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable {
// This should only be constructed via static factory methods, such as
// nattKeepalivePacket
private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
@@ -77,4 +78,18 @@
return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array());
}
+
+ /**
+ * Convert this NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
+ */
+ @NonNull
+ public NattKeepalivePacketDataParcelable toStableParcelable() {
+ final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
+
+ parcel.srcAddress = srcAddress.getAddress();
+ parcel.srcPort = srcPort;
+ parcel.dstAddress = dstAddress.getAddress();
+ parcel.dstPort = dstPort;
+ return parcel;
+ }
}
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
index 3b2e34a..07525a6 100644
--- a/tests/net/common/Android.bp
+++ b/tests/net/common/Android.bp
@@ -23,6 +23,7 @@
"androidx.test.rules",
"frameworks-net-testutils",
"junit",
+ "mockito-target-minus-junit4",
],
libs: [
"android.test.base.stubs",
diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java
new file mode 100644
index 0000000..eed7159
--- /dev/null
+++ b/tests/net/common/java/android/net/CaptivePortalTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 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.net;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.RemoteException;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CaptivePortalTest {
+ private static final int DEFAULT_TIMEOUT_MS = 5000;
+ private static final String TEST_PACKAGE_NAME = "com.google.android.test";
+
+ private final class MyCaptivePortalImpl extends ICaptivePortal.Stub {
+ int mCode = -1;
+ String mPackageName = null;
+
+ @Override
+ public void appResponse(final int response) throws RemoteException {
+ mCode = response;
+ }
+
+ @Override
+ public void logEvent(int eventId, String packageName) throws RemoteException {
+ mCode = eventId;
+ mPackageName = packageName;
+ }
+ }
+
+ private interface TestFunctor {
+ void useCaptivePortal(CaptivePortal o);
+ }
+
+ private MyCaptivePortalImpl runCaptivePortalTest(TestFunctor f) {
+ final MyCaptivePortalImpl cp = new MyCaptivePortalImpl();
+ f.useCaptivePortal(new CaptivePortal(cp.asBinder()));
+ return cp;
+ }
+
+ @Test
+ public void testReportCaptivePortalDismissed() {
+ final MyCaptivePortalImpl result =
+ runCaptivePortalTest(c -> c.reportCaptivePortalDismissed());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_DISMISSED);
+ }
+
+ @Test
+ public void testIgnoreNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.ignoreNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_UNWANTED);
+ }
+
+ @Test
+ public void testUseNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.useNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS);
+ }
+
+ @Test
+ public void testLogEvent() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent(
+ MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY,
+ TEST_PACKAGE_NAME));
+ assertEquals(result.mCode, MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
+ assertEquals(result.mPackageName, TEST_PACKAGE_NAME);
+ }
+}
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index ad76388..6bc7c1b 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -33,6 +33,8 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
@@ -585,4 +587,20 @@
nc2.set(nc1); // Overwrites, as opposed to combineCapabilities
assertEquals(nc1, nc2);
}
+
+ @Test
+ public void testGetTransportTypes() {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ nc.addTransportType(TRANSPORT_CELLULAR);
+ nc.addTransportType(TRANSPORT_WIFI);
+ nc.addTransportType(TRANSPORT_VPN);
+ nc.addTransportType(TRANSPORT_TEST);
+
+ final int[] transportTypes = nc.getTransportTypes();
+ assertEquals(4, transportTypes.length);
+ assertEquals(TRANSPORT_CELLULAR, transportTypes[0]);
+ assertEquals(TRANSPORT_WIFI, transportTypes[1]);
+ assertEquals(TRANSPORT_VPN, transportTypes[2]);
+ assertEquals(TRANSPORT_TEST, transportTypes[3]);
+ }
}
diff --git a/tests/net/common/java/android/net/NetworkTest.java b/tests/net/common/java/android/net/NetworkTest.java
index 0bee7cd..bef66b2 100644
--- a/tests/net/common/java/android/net/NetworkTest.java
+++ b/tests/net/common/java/android/net/NetworkTest.java
@@ -155,4 +155,12 @@
private static <T> void assertNotEqual(T t1, T t2) {
assertFalse(Objects.equals(t1, t2));
}
+
+ @Test
+ public void testGetPrivateDnsBypassingCopy() {
+ final Network copy = mNetwork.getPrivateDnsBypassingCopy();
+ assertEquals(mNetwork.netId, copy.netId);
+ assertNotEqual(copy.netId, copy.getNetIdForResolv());
+ assertNotEqual(mNetwork.getNetIdForResolv(), copy.getNetIdForResolv());
+ }
}
diff --git a/tests/net/common/java/android/net/StaticIpConfigurationTest.java b/tests/net/common/java/android/net/StaticIpConfigurationTest.java
index 8449ca7..5096be2 100644
--- a/tests/net/common/java/android/net/StaticIpConfigurationTest.java
+++ b/tests/net/common/java/android/net/StaticIpConfigurationTest.java
@@ -31,7 +31,9 @@
import org.junit.runner.RunWith;
import java.net.InetAddress;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
@RunWith(AndroidJUnit4.class)
@@ -46,6 +48,7 @@
private static final InetAddress DNS2 = IpAddress("8.8.4.4");
private static final InetAddress DNS3 = IpAddress("4.2.2.2");
private static final String IFACE = "eth0";
+ private static final String FAKE_DOMAINS = "google.com";
private static InetAddress IpAddress(String addr) {
return InetAddress.parseNumericAddress(addr);
@@ -69,7 +72,7 @@
s.dnsServers.add(DNS1);
s.dnsServers.add(DNS2);
s.dnsServers.add(DNS3);
- s.domains = "google.com";
+ s.domains = FAKE_DOMAINS;
return s;
}
@@ -178,8 +181,8 @@
expected.addDnsServer(DNS3);
assertEquals(expected, s.toLinkProperties(IFACE));
- s.domains = "google.com";
- expected.setDomains("google.com");
+ s.domains = FAKE_DOMAINS;
+ expected.setDomains(FAKE_DOMAINS);
assertEquals(expected, s.toLinkProperties(IFACE));
s.gateway = null;
@@ -218,4 +221,53 @@
StaticIpConfiguration s2 = passThroughParcel(s);
assertEquals(s, s2);
}
+
+ @Test
+ public void testBuilder() {
+ final ArrayList<InetAddress> dnsServers = new ArrayList<>();
+ dnsServers.add(DNS1);
+
+ final StaticIpConfiguration s = new StaticIpConfiguration.Builder()
+ .setIpAddress(ADDR)
+ .setGateway(GATEWAY)
+ .setDomains(FAKE_DOMAINS)
+ .setDnsServers(dnsServers)
+ .build();
+
+ assertEquals(s.ipAddress, s.getIpAddress());
+ assertEquals(ADDR, s.getIpAddress());
+ assertEquals(s.gateway, s.getGateway());
+ assertEquals(GATEWAY, s.getGateway());
+ assertEquals(s.domains, s.getDomains());
+ assertEquals(FAKE_DOMAINS, s.getDomains());
+ assertTrue(s.dnsServers.equals(s.getDnsServers()));
+ assertEquals(1, s.getDnsServers().size());
+ assertEquals(DNS1, s.getDnsServers().get(0));
+ }
+
+ @Test
+ public void testAddDnsServers() {
+ final StaticIpConfiguration s = new StaticIpConfiguration((StaticIpConfiguration) null);
+ checkEmpty(s);
+
+ s.addDnsServer(DNS1);
+ assertEquals(1, s.getDnsServers().size());
+ assertEquals(DNS1, s.getDnsServers().get(0));
+
+ s.addDnsServer(DNS2);
+ s.addDnsServer(DNS3);
+ assertEquals(3, s.getDnsServers().size());
+ assertEquals(DNS2, s.getDnsServers().get(1));
+ assertEquals(DNS3, s.getDnsServers().get(2));
+ }
+
+ @Test
+ public void testGetRoutes() {
+ final StaticIpConfiguration s = makeTestObject();
+ final List<RouteInfo> routeInfoList = s.getRoutes(IFACE);
+
+ assertEquals(2, routeInfoList.size());
+ assertEquals(new RouteInfo(ADDR, (InetAddress) null, IFACE), routeInfoList.get(0));
+ assertEquals(new RouteInfo((IpPrefix) null, GATEWAY, IFACE), routeInfoList.get(1));
+ }
}
diff --git a/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt b/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt
new file mode 100644
index 0000000..8d055c9
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 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.net.metrics;
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ApfProgramEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ private infix fun Int.hasFlag(flag: Int) = (this and (1 shl flag)) != 0
+
+ @Test
+ fun testBuilderAndParcel() {
+ val apfProgramEvent = ApfProgramEvent.Builder()
+ .setLifetime(1)
+ .setActualLifetime(2)
+ .setFilteredRas(3)
+ .setCurrentRas(4)
+ .setProgramLength(5)
+ .setFlags(true, true)
+ .build()
+
+ assertEquals(1, apfProgramEvent.lifetime)
+ assertEquals(2, apfProgramEvent.actualLifetime)
+ assertEquals(3, apfProgramEvent.filteredRas)
+ assertEquals(4, apfProgramEvent.currentRas)
+ assertEquals(5, apfProgramEvent.programLength)
+ assertEquals(ApfProgramEvent.flagsFor(true, true), apfProgramEvent.flags)
+
+ testParcel(apfProgramEvent, 6)
+ }
+
+ @Test
+ fun testFlagsFor() {
+ var flags = ApfProgramEvent.flagsFor(false, false)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(true, false)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(false, true)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(true, true)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/ApfStatsTest.kt b/tests/net/common/java/android/net/metrics/ApfStatsTest.kt
new file mode 100644
index 0000000..f8eb40c
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ApfStatsTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 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.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ApfStatsTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testBuilderAndParcel() {
+ val apfStats = ApfStats.Builder()
+ .setDurationMs(Long.MAX_VALUE)
+ .setReceivedRas(1)
+ .setMatchingRas(2)
+ .setDroppedRas(3)
+ .setZeroLifetimeRas(4)
+ .setParseErrors(5)
+ .setProgramUpdates(6)
+ .setProgramUpdatesAll(7)
+ .setProgramUpdatesAllowingMulticast(8)
+ .setMaxProgramSize(9)
+ .build()
+
+ assertEquals(Long.MAX_VALUE, apfStats.durationMs)
+ assertEquals(1, apfStats.receivedRas)
+ assertEquals(2, apfStats.matchingRas)
+ assertEquals(3, apfStats.droppedRas)
+ assertEquals(4, apfStats.zeroLifetimeRas)
+ assertEquals(5, apfStats.parseErrors)
+ assertEquals(6, apfStats.programUpdates)
+ assertEquals(7, apfStats.programUpdatesAll)
+ assertEquals(8, apfStats.programUpdatesAllowingMulticast)
+ assertEquals(9, apfStats.maxProgramSize)
+
+ testParcel(apfStats, 10)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt b/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
index e191953..e9d5e6d 100644
--- a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
+++ b/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
@@ -13,9 +13,7 @@
import org.junit.runner.RunWith
private const val TEST_ERROR_CODE = 12345
-/**
- * DHCP Optional Type: DHCP Subnet Mask (Copy from DhcpPacket.java)
- */
+//DHCP Optional Type: DHCP Subnet Mask (Copy from DhcpPacket.java due to it's protected)
private const val DHCP_SUBNET_MASK = 1
@RunWith(AndroidJUnit4::class)
diff --git a/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java b/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java
new file mode 100644
index 0000000..d4780d3
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 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.net.metrics;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.net.ConnectivityMetricsEvent;
+import android.net.IIpConnectivityMetrics;
+import android.net.Network;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.BitUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpConnectivityLogTest {
+ private static final int FAKE_NET_ID = 100;
+ private static final int[] FAKE_TRANSPORT_TYPES = BitUtils.unpackBits(TRANSPORT_WIFI);
+ private static final long FAKE_TIME_STAMP = System.currentTimeMillis();
+ private static final String FAKE_INTERFACE_NAME = "test";
+ private static final IpReachabilityEvent FAKE_EV =
+ new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
+
+ @Mock IIpConnectivityMetrics mMockService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testLoggingEvents() throws Exception {
+ IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+ assertTrue(logger.log(FAKE_EV));
+ assertTrue(logger.log(FAKE_TIME_STAMP, FAKE_EV));
+ assertTrue(logger.log(FAKE_NET_ID, FAKE_TRANSPORT_TYPES, FAKE_EV));
+ assertTrue(logger.log(new Network(FAKE_NET_ID), FAKE_TRANSPORT_TYPES, FAKE_EV));
+ assertTrue(logger.log(FAKE_INTERFACE_NAME, FAKE_EV));
+ assertTrue(logger.log(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID, TRANSPORT_WIFI,
+ FAKE_INTERFACE_NAME)));
+
+ List<ConnectivityMetricsEvent> got = verifyEvents(6);
+ assertEventsEqual(makeExpectedEvent(got.get(0).timestamp, 0, 0, null), got.get(0));
+ assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, 0, 0, null), got.get(1));
+ assertEventsEqual(makeExpectedEvent(got.get(2).timestamp, FAKE_NET_ID,
+ TRANSPORT_WIFI, null), got.get(2));
+ assertEventsEqual(makeExpectedEvent(got.get(3).timestamp, FAKE_NET_ID,
+ TRANSPORT_WIFI, null), got.get(3));
+ assertEventsEqual(makeExpectedEvent(got.get(4).timestamp, 0, 0, FAKE_INTERFACE_NAME),
+ got.get(4));
+ assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID,
+ TRANSPORT_WIFI, FAKE_INTERFACE_NAME), got.get(5));
+ }
+
+ @Test
+ public void testLoggingEventsWithMultipleCallers() throws Exception {
+ IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+ final int nCallers = 10;
+ final int nEvents = 10;
+ for (int n = 0; n < nCallers; n++) {
+ final int i = n;
+ new Thread() {
+ public void run() {
+ for (int j = 0; j < nEvents; j++) {
+ assertTrue(logger.log(makeExpectedEvent(
+ FAKE_TIME_STAMP + i * 100 + j,
+ FAKE_NET_ID + i * 100 + j,
+ ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR,
+ FAKE_INTERFACE_NAME)));
+ }
+ }
+ }.start();
+ }
+
+ List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
+ Collections.sort(got, EVENT_COMPARATOR);
+ Iterator<ConnectivityMetricsEvent> iter = got.iterator();
+ for (int i = 0; i < nCallers; i++) {
+ for (int j = 0; j < nEvents; j++) {
+ final long expectedTimestamp = FAKE_TIME_STAMP + i * 100 + j;
+ final int expectedNetId = FAKE_NET_ID + i * 100 + j;
+ final long expectedTransports =
+ ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR;
+ assertEventsEqual(makeExpectedEvent(expectedTimestamp, expectedNetId,
+ expectedTransports, FAKE_INTERFACE_NAME), iter.next());
+ }
+ }
+ }
+
+ private List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
+ ArgumentCaptor<ConnectivityMetricsEvent> captor =
+ ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
+ verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
+ return captor.getAllValues();
+ }
+
+ private List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
+ return verifyEvents(n, 10);
+ }
+
+
+ private ConnectivityMetricsEvent makeExpectedEvent(long timestamp, int netId, long transports,
+ String ifname) {
+ ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
+ ev.timestamp = timestamp;
+ ev.data = FAKE_EV;
+ ev.netId = netId;
+ ev.transports = transports;
+ ev.ifname = ifname;
+ return ev;
+ }
+
+ /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
+ private void assertEventsEqual(ConnectivityMetricsEvent expected,
+ ConnectivityMetricsEvent got) {
+ assertEquals(expected.data, got.data);
+ assertEquals(expected.timestamp, got.timestamp);
+ assertEquals(expected.netId, got.netId);
+ assertEquals(expected.transports, got.transports);
+ assertEquals(expected.ifname, got.ifname);
+ }
+
+ static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
+ Comparator.comparingLong((ev) -> ev.timestamp);
+}
diff --git a/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt b/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
new file mode 100644
index 0000000..d76ebf6
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 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.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class IpReachabilityEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (IpReachabilityEvent.PROBE..IpReachabilityEvent.PROVISIONING_LOST_ORGANIC).forEach {
+ val ipReachabilityEvent = IpReachabilityEvent(it)
+ assertEquals(it, ipReachabilityEvent.eventType)
+
+ testParcel(ipReachabilityEvent, 1)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/RaEventTest.kt b/tests/net/common/java/android/net/metrics/RaEventTest.kt
new file mode 100644
index 0000000..f38d328
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/RaEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 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.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val NO_LIFETIME: Long = -1L
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class RaEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ var raEvent = RaEvent.Builder().build()
+ assertEquals(NO_LIFETIME, raEvent.routerLifetime)
+ assertEquals(NO_LIFETIME, raEvent.prefixValidLifetime)
+ assertEquals(NO_LIFETIME, raEvent.prefixPreferredLifetime)
+ assertEquals(NO_LIFETIME, raEvent.routeInfoLifetime)
+ assertEquals(NO_LIFETIME, raEvent.rdnssLifetime)
+ assertEquals(NO_LIFETIME, raEvent.dnsslLifetime)
+
+ raEvent = RaEvent.Builder()
+ .updateRouterLifetime(1)
+ .updatePrefixValidLifetime(2)
+ .updatePrefixPreferredLifetime(3)
+ .updateRouteInfoLifetime(4)
+ .updateRdnssLifetime(5)
+ .updateDnsslLifetime(6)
+ .build()
+ assertEquals(1, raEvent.routerLifetime)
+ assertEquals(2, raEvent.prefixValidLifetime)
+ assertEquals(3, raEvent.prefixPreferredLifetime)
+ assertEquals(4, raEvent.routeInfoLifetime)
+ assertEquals(5, raEvent.rdnssLifetime)
+ assertEquals(6, raEvent.dnsslLifetime)
+
+ raEvent = RaEvent.Builder()
+ .updateRouterLifetime(Long.MIN_VALUE)
+ .updateRouterLifetime(Long.MAX_VALUE)
+ .build()
+ assertEquals(Long.MIN_VALUE, raEvent.routerLifetime)
+
+ raEvent = RaEvent(1, 2, 3, 4, 5, 6)
+ assertEquals(1, raEvent.routerLifetime)
+ assertEquals(2, raEvent.prefixValidLifetime)
+ assertEquals(3, raEvent.prefixPreferredLifetime)
+ assertEquals(4, raEvent.routeInfoLifetime)
+ assertEquals(5, raEvent.rdnssLifetime)
+ assertEquals(6, raEvent.dnsslLifetime)
+
+ testParcel(raEvent, 6)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt b/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
new file mode 100644
index 0000000..c0cef8f
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 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.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import java.lang.reflect.Modifier
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val FIRST_VALIDATION: Int = 1 shl 8
+private const val REVALIDATION: Int = 2 shl 8
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ValidationProbeEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ private infix fun Int.hasType(type: Int) = (type and this) == type
+
+ @Test
+ fun testBuilderAndParcel() {
+ var validationProbeEvent = ValidationProbeEvent.Builder()
+ .setProbeType(ValidationProbeEvent.PROBE_DNS, false).build()
+
+ assertTrue(validationProbeEvent.probeType hasType REVALIDATION)
+
+ validationProbeEvent = ValidationProbeEvent.Builder()
+ .setDurationMs(Long.MAX_VALUE)
+ .setProbeType(ValidationProbeEvent.PROBE_DNS, true)
+ .setReturnCode(ValidationProbeEvent.DNS_SUCCESS)
+ .build()
+
+ assertEquals(Long.MAX_VALUE, validationProbeEvent.durationMs)
+ assertTrue(validationProbeEvent.probeType hasType ValidationProbeEvent.PROBE_DNS)
+ assertTrue(validationProbeEvent.probeType hasType FIRST_VALIDATION)
+ assertEquals(ValidationProbeEvent.DNS_SUCCESS, validationProbeEvent.returnCode)
+
+ testParcel(validationProbeEvent, 3)
+ }
+
+ @Test
+ fun testGetProbeName() {
+ val probeFields = ValidationProbeEvent::class.java.declaredFields.filter {
+ it.type == Int::class.javaPrimitiveType
+ && Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers)
+ && it.name.contains("PROBE")
+ }
+
+ probeFields.forEach {
+ val intValue = it.getInt(null)
+ val stringValue = ValidationProbeEvent.getProbeName(intValue)
+ assertEquals(it.name, stringValue)
+ }
+
+ }
+}
diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java
index 18c6768..8ff2de9 100644
--- a/tests/net/java/android/net/IpMemoryStoreTest.java
+++ b/tests/net/java/android/net/IpMemoryStoreTest.java
@@ -16,10 +16,26 @@
package android.net;
-import static org.mockito.ArgumentMatchers.any;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.net.ipmemorystore.Blob;
+import android.net.ipmemorystore.IOnStatusListener;
+import android.net.ipmemorystore.NetworkAttributes;
+import android.net.ipmemorystore.NetworkAttributesParcelable;
+import android.net.ipmemorystore.Status;
+import android.os.RemoteException;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -27,28 +43,57 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IpMemoryStoreTest {
+ private static final String TAG = IpMemoryStoreTest.class.getSimpleName();
+ private static final String TEST_CLIENT_ID = "testClientId";
+ private static final String TEST_DATA_NAME = "testData";
+ private static final String TEST_OTHER_DATA_NAME = TEST_DATA_NAME + "Other";
+ private static final byte[] TEST_BLOB_DATA = new byte[] { -3, 6, 8, -9, 12,
+ -128, 0, 89, 112, 91, -34 };
+ private static final NetworkAttributes TEST_NETWORK_ATTRIBUTES = buildTestNetworkAttributes(
+ "hint", 219);
+
@Mock
Context mMockContext;
@Mock
NetworkStackClient mNetworkStackClient;
@Mock
IIpMemoryStore mMockService;
+ @Mock
+ IOnStatusListener mIOnStatusListener;
IpMemoryStore mStore;
+ @Captor
+ ArgumentCaptor<IIpMemoryStoreCallbacks> mCbCaptor;
+ @Captor
+ ArgumentCaptor<NetworkAttributesParcelable> mNapCaptor;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- doAnswer(invocation -> {
- ((IIpMemoryStoreCallbacks) invocation.getArgument(0))
- .onIpMemoryStoreFetched(mMockService);
- return null;
- }).when(mNetworkStackClient).fetchIpMemoryStore(any());
+ }
+
+ private void startIpMemoryStore(boolean supplyService) {
+ if (supplyService) {
+ doAnswer(invocation -> {
+ ((IIpMemoryStoreCallbacks) invocation.getArgument(0))
+ .onIpMemoryStoreFetched(mMockService);
+ return null;
+ }).when(mNetworkStackClient).fetchIpMemoryStore(any());
+ } else {
+ doNothing().when(mNetworkStackClient).fetchIpMemoryStore(mCbCaptor.capture());
+ }
mStore = new IpMemoryStore(mMockContext) {
@Override
protected NetworkStackClient getNetworkStackClient() {
@@ -57,24 +102,228 @@
};
}
- @Test
- public void testNetworkAttributes() {
- // TODO : implement this
+ private static NetworkAttributes buildTestNetworkAttributes(String hint, int mtu) {
+ return new NetworkAttributes.Builder()
+ .setGroupHint(hint)
+ .setMtu(mtu)
+ .build();
}
@Test
- public void testPrivateData() {
- // TODO : implement this
+ public void testNetworkAttributes() throws Exception {
+ startIpMemoryStore(true);
+ final String l2Key = "fakeKey";
+
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ verify(mMockService, times(1)).storeNetworkAttributes(eq(l2Key),
+ mNapCaptor.capture(), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+
+ verify(mMockService, times(1)).retrieveNetworkAttributes(eq(l2Key), any());
}
@Test
- public void testFindL2Key() {
- // TODO : implement this
+ public void testPrivateData() throws RemoteException {
+ startIpMemoryStore(true);
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ verify(mMockService, times(1)).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+ verify(mMockService, times(1)).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
}
@Test
- public void testIsSameNetwork() {
- // TODO : implement this
+ public void testFindL2Key()
+ throws UnknownHostException, RemoteException, Exception {
+ startIpMemoryStore(true);
+ final String l2Key = "fakeKey";
+
+ mStore.findL2Key(TEST_NETWORK_ATTRIBUTES,
+ (status, key) -> {
+ assertTrue("Retrieve network sameness not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ });
+ verify(mMockService, times(1)).findL2Key(mNapCaptor.capture(), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
}
+ @Test
+ public void testIsSameNetwork() throws UnknownHostException, RemoteException {
+ startIpMemoryStore(true);
+ final String l2Key1 = "fakeKey1";
+ final String l2Key2 = "fakeKey2";
+
+ mStore.isSameNetwork(l2Key1, l2Key2,
+ (status, answer) -> {
+ assertFalse("Retrieve network sameness suspiciously successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(Status.ERROR_ILLEGAL_ARGUMENT, status.resultCode);
+ assertNull(answer);
+ });
+ verify(mMockService, times(1)).isSameNetwork(eq(l2Key1), eq(l2Key2), any());
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequests() throws Exception {
+ startIpMemoryStore(false);
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // get ipms service ready
+ mCbCaptor.getValue().onIpMemoryStoreFetched(mMockService);
+
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), any());
+ inOrder.verify(mMockService).retrieveNetworkAttributes(eq(l2Key), any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequestsWithException() throws Exception {
+ startIpMemoryStore(true);
+ doThrow(RemoteException.class).when(mMockService).retrieveNetworkAttributes(any(), any());
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // verify the rest of the queue is still processed in order even if the remote exception
+ // occurs when calling one or more requests
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequestsCallbackFunctionWithException() throws Exception {
+ startIpMemoryStore(true);
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ throw new RuntimeException("retrieveNetworkAttributes test");
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ throw new RuntimeException("storeBlob test");
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // verify the rest of the queue is still processed in order even if when one or more
+ // callback throw the remote exception
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(),
+ any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 64672bd..3c5bb6a 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
@@ -103,6 +105,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
@@ -146,6 +149,7 @@
import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
+import android.os.Binder;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
@@ -272,6 +276,7 @@
@Mock IDnsResolver mMockDnsResolver;
@Mock INetd mMockNetd;
@Mock NetworkStackClient mNetworkStack;
+ @Mock PackageManager mPackageManager;
@Mock UserManager mUserManager;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
@@ -357,7 +362,12 @@
public Resources getResources() {
return mResources;
}
- }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+ }
public void waitForIdle(int timeoutMsAsInt) {
long timeoutMs = timeoutMsAsInt;
@@ -557,6 +567,16 @@
protected void preventAutomaticReconnect() {
mPreventReconnectReceived.open();
}
+
+ @Override
+ protected void addKeepalivePacketFilter(Message msg) {
+ Log.i(TAG, "Add keepalive packet filter.");
+ }
+
+ @Override
+ protected void removeKeepalivePacketFilter(Message msg) {
+ Log.i(TAG, "Remove keepalive packet filter.");
+ }
};
assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
@@ -1232,6 +1252,7 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
+ mockDefaultPackages();
FakeSettingsProvider.clearSettingsProvider();
mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
@@ -1284,7 +1305,24 @@
FakeSettingsProvider.clearSettingsProvider();
}
- private static int transportToLegacyType(int transport) {
+ private void mockDefaultPackages() throws Exception {
+ final String testPackageName = mContext.getPackageName();
+ final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
+ testPackageName, PackageManager.GET_PERMISSIONS);
+ when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
+ new String[] {testPackageName});
+ when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
+ eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
+
+ when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+ Arrays.asList(new PackageInfo[] {
+ buildPackageInfo(/* SYSTEM */ false, APP1_UID),
+ buildPackageInfo(/* SYSTEM */ false, APP2_UID),
+ buildPackageInfo(/* SYSTEM */ false, VPN_UID)
+ }));
+ }
+
+ private static int transportToLegacyType(int transport) {
switch (transport) {
case TRANSPORT_ETHERNET:
return TYPE_ETHERNET;
@@ -3816,6 +3854,9 @@
networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
testFactory.waitForRequests();
+ // unregister network callback - a no-op, but should not fail
+ mCm.unregisterNetworkCallback(networkCallback);
+
testFactory.unregister();
handlerThread.quit();
}
@@ -4891,7 +4932,10 @@
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(false);
waitForIdle();
- // CS tells netd about the empty DNS config for this network.
+
+ verify(mMockDnsResolver, times(1)).createNetworkCache(
+ eq(mCellNetworkAgent.getNetwork().netId));
+ // CS tells dnsresolver about the empty DNS config for this network.
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
reset(mMockDnsResolver);
@@ -4975,6 +5019,8 @@
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(false);
waitForIdle();
+ verify(mMockDnsResolver, times(1)).createNetworkCache(
+ eq(mCellNetworkAgent.getNetwork().netId));
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
mResolverParamsParcelCaptor.capture());
ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
@@ -5848,12 +5894,17 @@
cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
+ reset(mMockNetd);
when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
.thenReturn(getClatInterfaceConfig(myIpv4));
// Connect with ipv6 link properties. Expect prefix discovery to be started.
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(true);
+
+ verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
+ verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
+
networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
@@ -6045,7 +6096,7 @@
verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
verify(mMockDnsResolver, times(1))
- .clearResolverConfiguration(eq(mCellNetworkAgent.getNetwork().netId));
+ .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
// Disconnect wifi
ConditionVariable cv = waitForConnectivityBroadcasts(1);
@@ -6169,7 +6220,6 @@
}
@Test
- @Ignore
public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6196,7 +6246,6 @@
}
@Test
- @Ignore
public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6210,7 +6259,6 @@
}
@Test
- @Ignore
public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
throws Exception {
LinkProperties lp = new LinkProperties();
@@ -6226,7 +6274,6 @@
}
@Test
- @Ignore
public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6276,7 +6323,6 @@
}
@Test
- @Ignore
public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index d5b2c87..3a07166 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -21,11 +21,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -59,16 +56,11 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -98,48 +90,6 @@
}
@Test
- public void testLoggingEvents() throws Exception {
- IpConnectivityLog logger = new IpConnectivityLog(mMockService);
-
- assertTrue(logger.log(1, FAKE_EV));
- assertTrue(logger.log(2, FAKE_EV));
- assertTrue(logger.log(3, FAKE_EV));
-
- List<ConnectivityMetricsEvent> got = verifyEvents(3);
- assertEventsEqual(expectedEvent(1), got.get(0));
- assertEventsEqual(expectedEvent(2), got.get(1));
- assertEventsEqual(expectedEvent(3), got.get(2));
- }
-
- @Test
- public void testLoggingEventsWithMultipleCallers() throws Exception {
- IpConnectivityLog logger = new IpConnectivityLog(mMockService);
-
- final int nCallers = 10;
- final int nEvents = 10;
- for (int n = 0; n < nCallers; n++) {
- final int i = n;
- new Thread() {
- public void run() {
- for (int j = 0; j < nEvents; j++) {
- assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
- }
- }
- }.start();
- }
-
- List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
- Collections.sort(got, EVENT_COMPARATOR);
- Iterator<ConnectivityMetricsEvent> iter = got.iterator();
- for (int i = 0; i < nCallers; i++) {
- for (int j = 0; j < nEvents; j++) {
- int expectedTimestamp = 1 + i * 100 + j;
- assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
- }
- }
- }
-
- @Test
public void testBufferFlushing() {
String output1 = getdump("flush");
assertEquals("", output1);
@@ -653,16 +603,7 @@
return nai;
}
- List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
- ArgumentCaptor<ConnectivityMetricsEvent> captor =
- ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
- verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
- return captor.getAllValues();
- }
- List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
- return verifyEvents(n, 10);
- }
static void verifySerialization(String want, String output) {
try {
@@ -674,28 +615,4 @@
fail(e.toString());
}
}
-
- static String joinLines(String ... elems) {
- StringBuilder b = new StringBuilder();
- for (String s : elems) {
- b.append(s).append("\n");
- }
- return b.toString();
- }
-
- static ConnectivityMetricsEvent expectedEvent(int timestamp) {
- ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
- ev.timestamp = timestamp;
- ev.data = FAKE_EV;
- return ev;
- }
-
- /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
- static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
- assertEquals(expected.timestamp, got.timestamp);
- assertEquals(expected.data, got.data);
- }
-
- static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
- Comparator.comparingLong((ev) -> ev.timestamp);
}
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
index a83faf3..fb84611 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
+++ b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.connectivity.ipmemorystore;
+package com.android.server.net.ipmemorystore;
import static org.junit.Assert.assertEquals;